package networkInterface;

import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 * Classe récupérée sur Internet, à l'adresse
 * http://igm.univ-mlv.fr/~roussel/vuibert.old/chap6/InetAddressUtil.html Cette
 * classe permet de récupérer l'adresse de broadcast du réseau.
 * 
 */
public class InetAddressUtil {
	/**
	 * Donne le masque reseau associe a la classe d'une adresse Internet stockee
	 * dans quatre cases d'un tableau d'octets.
	 * 
	 * @param address
	 *            tableau d'octets contenant l'adresse Internet.
	 * @param offset
	 *            index du premier octet de l'adresse dans le tableau.
	 * @return l'objet adresse Internet contenant le masque réseau.
	 * @exception UnknownHostException
	 *                si l'adresse est de classe D ou E.
	 */
	public static InetAddress getMask(byte[] address, int offset)
			throws UnknownHostException {
		byte[] mask = new byte[4];
		if (address[offset] == 0) {
			throw new UnknownHostException();
		}
		mask[0] = (byte) 255;
		if ((address[offset] & 0x80000000) == 0) {
			// Adresse de classe A
			return byteToInetAddress(mask, 0);
		}
		mask[1] = (byte) 255;
		if ((address[offset] & 0x40) == 0) {
			// Adresse de classe B
			return byteToInetAddress(mask, 0);
		}
		if ((address[offset] & 0x20) == 0) {
			// Adresse de classe C
			mask[2] = (byte) 255;
			return byteToInetAddress(mask, 0);
		}
		// Adresse de classe D ou E
		throw new UnknownHostException();
	}

	/**
	 * Donne l'adresse de broadcast IP associee à la classe d'une adresse
	 * Internet stockee dans quatre cases d'un tableau d'octets.
	 * 
	 * @param address
	 *            tableau d'octets contenant l'adresse Internet.
	 * @param offset
	 *            index du premier octet de l'adresse dans le tableau.
	 * @return l'objet adresse Internet contenant l'adresse de broadcast.
	 * @exception UnknownHostException
	 *                si l'adresse est de classe D ou E.
	 */
	public static InetAddress getBroadcast(byte[] address, int offset)
			throws UnknownHostException {
		byte[] broadcast = new byte[4];
		broadcast[0] = address[offset];
		if ((address[offset] & 0x80000000) == 0) {
			// Adresse de classe A
			broadcast[1] = (byte) 255;
			broadcast[2] = (byte) 255;
			broadcast[3] = (byte) 255;
			return byteToInetAddress(broadcast, 0);
		}
		broadcast[1] = address[offset + 1];
		if ((address[offset] & 0x40) == 0) {
			// Adresse de classe B
			broadcast[2] = (byte) 255;
			broadcast[3] = (byte) 255;
			return byteToInetAddress(broadcast, 0);
		}
		if ((address[offset] & 0x20) == 0) {
			// Adresse de classe C
			broadcast[2] = address[offset + 2];
			broadcast[3] = (byte) 255;
			return byteToInetAddress(broadcast, 0);
		}
		// Adresse de classe D ou E
		throw new UnknownHostException();
	}

	/**
	 * Cette methode a ete modifiee par l'ensemble du groupe de TP pour
	 * permettre d'envoyer sur toutes les interfaces reseau d'un ordinateur car
	 * sinon, c'etait souvent l'adresse de loopback qui ete selectionnee
	 * 
	 * @return l'objet adresse Internet de broadcast.
	 */
	public static InetAddress getLocalBroadcast() throws UnknownHostException {
		// byte[] localAddress = InetAddress.getLocalHost().getAddress();
		// return getBroadcast(localAddress, 0);
		byte[] addr = { (byte) 255, (byte) 255, (byte) 255, (byte) 255 };
		return InetAddress.getByAddress(addr);
	}

	/**
	 * Transforme une adresse Internet stockee dans quatre cases d'un tableau de
	 * byte en un objet InetAddress.
	 * 
	 * @param address
	 *            tableau d'octets contenant l'adresse Internet.
	 * @param offset
	 *            index du premier octet de l'adresse dans le tableau.
	 * @return l'objet adresse Internet.
	 */
	public static InetAddress byteToInetAddress(byte[] address, int offset)
			throws UnknownHostException {
		StringBuffer buffer = new StringBuffer(15);
		int tmp;
		for (int i = 0; i < 4; i++) {
			// Récupère la valeur non signee de l'octet
			tmp = address[offset + i] & 0x7F;
			// Récupère le bit de signe qui, à cause de la
			// promotion entière de l'octet, se trouve dans
			// l'octet de poids fort d'un entier
			if ((address[offset + i] & 80000000) != 0)
				tmp = tmp | 0x80;

			buffer.append(tmp);
			if (i != 3)
				buffer.append('.');
		}
		return InetAddress.getByName(buffer.toString());
	}
}
